package com.jyw.system.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.jyw.common.constant.ConfigKeyConstant;
import com.jyw.common.utils.DateUtils;
import com.jyw.common.utils.SecurityUtils;
import com.jyw.system.domain.SysFileInfo;
import com.jyw.system.domain.vo.MinioConfigVO;
import com.jyw.system.domain.vo.SimpleFileVo;
import com.jyw.system.mapper.SysFileInfoMapper;
import com.jyw.system.service.ISysConfigService;
import com.jyw.system.service.ISysFileInfoService;
import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统附件Service业务层处理
 *
 * @author system
 * @date 2023-08-17
 */
@Service
public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFileInfo> implements ISysFileInfoService {

    @Resource
    private ISysConfigService configService;

    private String bucket;

    @Override
    public List<SimpleFileVo> upload(MultipartFile... files) {
        MinioClient minioClient = getMinioClient();
        String folders = getFolders();
        List<SysFileInfo> fileInfoList = Lists.newArrayList();
        for (MultipartFile file : files) {
            // UUID重命名
            String fileName = UUID.fastUUID().toString(true) + "." + FileUtil.getSuffix(file.getOriginalFilename());
            String filePath = StrUtil.format("{}{}", folders, fileName);
            InputStream fi = null;
            try {
                fi = file.getInputStream();
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .stream(fi, file.getSize(), PutObjectArgs.MIN_MULTIPART_SIZE)
                                .object(filePath)
                                .contentType(file.getContentType())
                                .bucket(this.bucket)
                                .build()
                );

            } catch (Exception e) {
                log.error("上传文件失败", e);
                continue;
            } finally {
                if (!ObjectUtils.isEmpty(fi)) {
                    try {
                        fi.close();
                    } catch (IOException e) {
                        log.error("关闭文件流失败", e);
                    }
                }
            }
            //封装数据库实体
            SysFileInfo fileInfo = new SysFileInfo();
            fileInfo.setUrl(filePath);
            fileInfo.setName(file.getOriginalFilename());
            fileInfo.setCreateUser(SecurityUtils.getUserId());
            fileInfo.setCreateTime(DateUtils.getNowDate());
            fileInfoList.add(fileInfo);
        }
        //保存数据库
        saveBatch(fileInfoList);
        //返回响应对象
        return fileInfoList.stream().map(data -> data.toSimple()).collect(Collectors.toList());
    }

    @Override
    public String previewFile(String url) throws Exception {
        MinioClient minioClient = getMinioClient();
        GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
                .builder().bucket(bucket).object(url).method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(build);
    }

    @Override
    public InputStream download(String url) throws Exception {
        MinioClient minioClient = getMinioClient();
        InputStream stream = minioClient.getObject(
                GetObjectArgs.builder().bucket(bucket).object(url).build());
        return stream;
    }


    private String getFolders() {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(StrUtil.format("yyyy/MM/dd/")));
    }

    public MinioClient getMinioClient() {
        MinioConfigVO config = JSONObject.parse(configService.selectConfigByKey(ConfigKeyConstant.MINIO_CONFIG)).toJavaObject(MinioConfigVO.class);
        this.bucket = config.getBucket();
        return MinioClient.builder().endpoint(config.getEndpoint()).credentials(config.getAccessKey(), config.getSecretKey()).build();
    }

}
